package com.wei.czz.framework.admin.controller;

import com.wei.czz.common.annotation.Auth;
import com.wei.czz.common.annotation.Resubmit;
import com.wei.czz.common.dto.admin.UserDto;
import com.wei.czz.common.dto.admin.user.UserRoleDto;
import com.wei.czz.common.dto.admin.userRole.UserRoleViewDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.admin.userRole.RelationModeEnum;
import com.wei.czz.common.jsr303.group.OrderSearch;
import com.wei.czz.common.property.BatchProperty;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.tool.Result;
import com.wei.czz.common.vo.admin.user.UserRoleVo;
import com.wei.czz.common.vo.admin.userRole.UpdateUserRoleVo;
import com.wei.czz.common.vo.admin.userRole.UserRoleFormVo;
import com.wei.czz.framework.admin.manager.RoleManager;
import com.wei.czz.framework.admin.manager.UserRoleManager;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-09-20 21:58:17
 * className: UserRoleController 用户与角色操作请求接口类
 * version: 1.0
 * description:
 */
@RestController
@RequestMapping("sys/user-role")
@AllArgsConstructor
public class UserRoleController {

    private static final Logger log = LoggerFactory.getLogger(UserRoleController.class);

    private final BatchProperty batchProperty;

    private final UserRoleManager userRoleManager;

    private final RoleManager roleManager;

    /**
     * 添加用户关联角色接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-部门关联角色页-角色关联用户弹出框调用
     * <p>
     * 此接口会校验是否重复提交
     * @param userRoleVo 参数对象
     */
    @Resubmit(spEL = "'saveUserRole' + #userPo.userId", message = "用户关联角色")
    @PostMapping("/save")
    @Auth(permit = "system:dept-role:save")
    public Result<Object> saveUserRole(@Validated @RequestBody UserRoleVo userRoleVo) {
        log.info("开始添加用户关联角色业务。{}", userRoleVo);

        List<Long> userIdList = userRoleVo.getUserIdList();
        if (batchProperty.getMaxSize() < userIdList.size()) {
            log.warn("用户主键列表超限。batch.size={} list.size={}", batchProperty.getMaxSize(), userIdList.size());
            return Result.clientFail("一次角色关联用户操作最多允许同时关联" + batchProperty.getMaxSize() + "个用户");
        }

        userRoleManager.saveRoleUser(userRoleVo.getRoleId(), userIdList, RelationModeEnum.AUTH.getValue());

        log.info("添加用户关联角色业务结束");
        return Result.success();
    }

    /**
     * 获取用户关联角色主键接口
     * 根据用户主键，获取用户关联的角色主键数据
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-用户管理页-用户操作弹出框中调用
     *
     * @param userId 用户主键
     * @return 角色主键数据
     */
    @GetMapping("/roleIds")
    @Auth(permit = { "system:user:save", "system:user:update" })
    public Result<List<String>> getUserRoleIdList(@RequestParam("userId") Long userId) {
        log.info("开始获取角色主键数据业务。userId={}", userId);

        List<String> roleIdList = roleManager.getUserRoleIdList(userId);

        log.info("获取角色主键数据业务结束");
        return Result.success(roleIdList);
    }

    /**
     * 获取用户关联角色列表接口
     * 根据用户主键，获取用户已关联的角色列表数据
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-用户关联角色弹出框中调用
     *
     * @param userId 用户主键
     * @return 角色列表
     */
    @GetMapping("/list")
    @Auth(permit = "system:dept-user:get")
    public Result<List<UserRoleViewDto>> getUserRoleList(@RequestParam("userId") Long userId) {
        log.info("开始获取角色列表业务。userId={}", userId);

        List<UserRoleViewDto> roleDtoList = roleManager.getUserRoleList(userId);

        log.info("获取角色列表业务结束");
        return Result.success(roleDtoList);
    }

    /**
     * 获取角色已关联用户列表接口
     * 根据角色主键，查询角色已关联用户列表
     * <p>
     * 调用方：
     *  1、浏览器-后台-部门关联角色页-角色关联用户弹出框调用
     *
     * @param roleId 角色主键
     * @return 用户列表
     */
    @GetMapping("/relation/user/list")
    @Auth(permit = "system:dept-role:get")
    public Result<List<UserRoleDto>> getRoleUserList(@RequestParam("roleId") Long roleId) {
        log.info("开始获取角色已关联用户列表业务。roleId={}", roleId);

        List<UserRoleDto> userRoleDtoList = roleManager.getRoleUserList(roleId);

        log.info("获取角色已关联用户列表业务结束");
        return Result.success(userRoleDtoList);
    }

    /**
     * 分页获取角色关联用户接口
     * @param formVo 参数对象
     * @return 结果
     */
    @PostMapping("/page/list")
    @Auth(permit = { "blog:audit:group:manage" })
    public Result<PageDto<UserDto>> getRoleUserPageList(@Validated(OrderSearch.class) @RequestBody UserRoleFormVo formVo) {
        log.info("开始分页获取角色关联用户业务。{}", formVo);

        PageDto<UserDto> pageDto = roleManager.getRoleUserPageList(formVo);

        log.info("分页获取角色关联用户业务结束");
        return Result.success(pageDto);
    }

    /**
     * 更新用户关联角色接口
     * 根据用户主键和角色主键列表，更新用户关联的角色数据
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-部门关联用户页-用户关联角色弹出框调用
     *
     * @param updateUserRoleVo 参数对象
     * @return 不返回数据
     */
    @Resubmit(spEL = "'updateUserRole' + #userPo.userId", message = "更新用户关联角色")
    @PostMapping("/update")
    @Auth(permit = "system:dept-user:update")
    public Result<Object> updateUserRole(@Validated @RequestBody UpdateUserRoleVo updateUserRoleVo) {
        log.info("开始更新用户关联角色业务。{}", updateUserRoleVo);

        List<Long> roleIdList = updateUserRoleVo.getRoleIdList();
        if (batchProperty.getMaxSize() < roleIdList.size()) {
            log.warn("角色主键列表超限。batch.maxSize={} list.size={}", batchProperty.getMaxSize(), roleIdList.size());
            return Result.clientFail("一次用户关联角色操作最多允许同时关联" + batchProperty.getMaxSize() + "个角色");
        }

        userRoleManager.saveUserRole(updateUserRoleVo.getUserId(), roleIdList, RelationModeEnum.AUTH.getValue());

        log.info("更新用户关联角色业务结束");
        return Result.success();
    }

    /**
     * 解除用户关联角色接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-部门关联角色页-角色关联用户弹出框调用
     * <p>
     * 此接口会校验是否重复提交
     * @param relationIdList 关联主键列表
     * @return 结果
     */
    @Resubmit(message = "解除用户关联角色")
    @DeleteMapping("/unassociated")
    @Auth(permit = "system:dept-role:delete")
    public Result<Object> unassociatedUserRole(@RequestBody List<Long> relationIdList) {
        log.info("开始解除用户关联角色业务。relationIdList={}", relationIdList);
        if (relationIdList.isEmpty()) {
            return Result.clientFail("关联主键列表不能为空");
        }
        if (batchProperty.getMaxSize() < relationIdList.size()) {
            log.warn("用户关联角色删除数量超限。batch.size={} size={}", batchProperty.getMaxSize(), relationIdList.size());
            return Result.clientFail("一次删除最多允许同时删除" + batchProperty.getMaxSize() + "条数据");
        }

        userRoleManager.unassociatedUserRole(relationIdList);

        log.info("解除用户关联角色业务结束");
        return Result.success();
    }
}
